package com.xh.xyzp.oss.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xh.xyzp.common.constant.UserContext;
import com.xh.xyzp.common.enums.CommonStatusTypeEnum;
import com.xh.xyzp.oss.domain.dto.FileDto;
import com.xh.xyzp.oss.domain.entity.FileEntity;
import com.xh.xyzp.oss.domain.vo.req.FileUploadReq;
import com.xh.xyzp.oss.domain.vo.resp.FileResp;
import com.xh.xyzp.oss.factory.OssFactory;
import com.xh.xyzp.oss.mapper.FileMapper;
import com.xh.xyzp.oss.service.FileService;
import com.xh.xyzp.oss.service.OssStrategy;
import com.xh.xyzp.util.SnowFlakeIdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @Author: xainghao
 * @Description:
 * @Date: 2024-11-12  18:02
 */
@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, FileEntity> implements FileService {

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private OssFactory ossFactory;

    @Value("${url.backend}")
    private String backendUrl;


    @Override
    public FileResp upload(FileUploadReq req) {
        checkUploadParams(req);
        // 检查是否已经存在
        FileEntity findFile = checkIfUpload(req);
        if (Objects.nonNull(findFile)) {
            // 已经存在，无需上传OSS
            FileEntity saveFile = BeanUtil.copyProperties(findFile, FileEntity.class);
            saveFile.setUserId(UserContext.getUser().getId());
            saveFile.setId(new SnowFlakeIdWorker(1, 0).nextId());
            save(saveFile);

            FileResp fileResp = BeanUtil.copyProperties(saveFile, FileResp.class);
            fileResp.setDownloadUrl(getFileDownloadUrl(saveFile.getId()));
            return fileResp;
        }
        OssStrategy ossStrategy = ossFactory.getOssStrategy();
        // 保存到数据库
        FileEntity fileEntity = BeanUtil.copyProperties(req, FileEntity.class);
        fileEntity.setOssType(ossFactory.getOssType());
        fileEntity.setTotalSize(req.getFile().getSize());
        fileEntity.setUserId(UserContext.getUser().getId());
        fileEntity.setFilename(req.getFile().getOriginalFilename());

        // 保存到OSS
        FileDto fileDto = BeanUtil.copyProperties(fileEntity, FileDto.class);
        try {
            fileDto.setFileData(req.getFile().getBytes());
            fileDto.setMultipartFile(req.getFile());
            ossStrategy.saveFile(fileDto);
        } catch (Exception e){
            throw new ApiException("保存文件出错");
        }

        fileEntity.setFilePath(fileDto.getFilePath());
        fileEntity.setId(new SnowFlakeIdWorker(1, 0).nextId());
        fileEntity.setCreateTime(LocalDateTime.now());
        fileEntity.setUpdateTime(LocalDateTime.now());
        fileEntity.setStatus(CommonStatusTypeEnum.NORMAL.getKey());
        fileMapper.insert(fileEntity);

        FileResp fileResp = BeanUtil.copyProperties(fileEntity, FileResp.class);
        fileResp.setDownloadUrl(getFileDownloadUrl(fileEntity.getId()));
        return fileResp;
    }

    private FileEntity checkIfUpload(FileUploadReq req) {
        List<FileEntity> files = fileMapper.selectList(new LambdaQueryWrapper<FileEntity>()
                .eq(FileEntity::getFileMd5, req.getFileMd5()));
        if (CollectionUtil.isEmpty(files)) {
            return null;
        }
        return files.get(0);
    }

    private String getFileDownloadUrl(Long fileId) {
        return backendUrl + "/api/oss/download/" + fileId;
    }

    private void checkUploadParams(FileUploadReq req) {
        if(Objects.isNull(req) || Objects.isNull(req.getFile()) || StrUtil.isEmpty(req.getFileMd5())){
            throw new ApiException("必要参数不能为空");
        }
    }

    @Override
    public ResponseEntity<byte[]> download(Long fileId) {
        OssStrategy ossStrategy = ossFactory.getOssStrategy();
        FileEntity fileEntity = fileMapper.selectById(fileId);
        byte[] fileData = ossStrategy.getFile(fileEntity);
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileEntity.getFilename());
        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(fileData);
    }
}
